package com.spzx.auth.service;

import com.spzx.auth.form.RegisterBody;
import com.spzx.common.core.constant.CacheConstants;
import com.spzx.common.core.constant.Constants;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.constant.UserConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.enums.UserStatus;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.core.text.Convert;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.common.core.utils.ip.IpUtils;
import com.spzx.common.redis.service.RedisService;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.system.api.RemoteUserService;
import com.spzx.system.api.model.LoginUser;
import com.spzx.user.api.RemoteUserInfoService;
import com.spzx.user.api.domain.UpdateUserLogin;
import com.spzx.user.api.domain.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.prefs.BackingStoreException;

/**
 * ClassName: H5LoginService
 * Package: com.spzx.auth.service
 * Description:
 */
@Service
@Slf4j
public class H5LoginService {
    @Autowired
    private RedisService redisService;

    @Autowired
    private RemoteUserInfoService remoteUserInfoService;

    @Autowired
    private SysRecordLogService recordLogService;
    @Autowired
    private SysPasswordService passwordService;

    public R<?> register(RegisterBody registerBody) {
        String username = registerBody.getUsername();
        String password = registerBody.getPassword();
        String nickName = registerBody.getNickName() != null ? registerBody.getNickName() : username;
        String code = registerBody.getCode();
        //判断用户名密码是否为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            throw new ServiceException("用户/密码必须填写");
        }
        if (username.length() != 11) {
            throw new ServiceException("账户长度必须是11位");
        }
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new ServiceException("密码长度必须在5到20个字符之间");
        }

        //判断验证码是否有效
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("验证码必须填写");
        }
        Object cacheCode = redisService.getCacheObject("phone:code" + username);
        if (cacheCode == null) {
            throw new ServiceException("验证已过期");
        }
        if (!code.equals(cacheCode)) {
            throw new ServiceException("验证码错误");
        }

        //封装到UserInfo对象中
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(username);
        userInfo.setNickName(nickName);
        userInfo.setSex(0);
        userInfo.setStatus(1);
        userInfo.setAvatar("http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132");
        userInfo.setPassword(SecurityUtils.encryptPassword(password));
        R<Boolean> registerResult = remoteUserInfoService.register(userInfo, SecurityConstants.INNER);
        if (R.FAIL == registerResult.getCode()) {
            throw new ServiceException("注册失败:" + registerResult.getMsg());
        }
        recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功");
        return registerResult;
    }

    public LoginUser login(String username, String password) {
        //用户名 密码是否为空
        if (StringUtils.isAnyBlank(username, password)) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名/密码必须填写");
            throw new ServiceException("用户名/密码必须填写");
        }
        //密码格式是否正确
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "密码格式不正确");
            throw new ServiceException("密码格式不正确");
        }
        //判断用户名格式是否正确
        if (username.length() != 11) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "账户格式不正确");
            throw new ServiceException("账户格式不正确");
        }
        //判断用户是否在黑名单中
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾，访问IP已被列入系统黑名单");
        }
        //查询用户是否存在
        R<UserInfo> userInfoResult = remoteUserInfoService.getUserInfo(username, SecurityConstants.INNER);
        if (R.FAIL == userInfoResult.getCode()) {
            throw new ServiceException(userInfoResult.getMsg());
        }
        UserInfo userInfo = userInfoResult.getData();
        if (userInfo == null) {
            throw new ServiceException("用户不存在");
        }
        //判断用户的状态是否正常
        if (UserStatus.DISABLE.getCode().equals(userInfo.getStatus()) ) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + username + " 已停用");
        }

        //判断密码是否正确
        LoginUser loginUser = new LoginUser();
        loginUser.setUserid(userInfo.getId());
        loginUser.setUsername(userInfo.getUsername());
        loginUser.setStatus(userInfo.getStatus().toString());
        loginUser.setPassword(userInfo.getPassword());
        passwordService.validate(loginUser,password);

        //密码脱敏
        loginUser.setPassword(null);

        //登录成功记录登录日志
        recordLogService.recordLogininfor(username,Constants.LOGIN_SUCCESS,"登录成功");

        //更新用户表的登录ip和登录时间
        UpdateUserLogin updateUserLogin = new UpdateUserLogin();
        updateUserLogin.setUserId(userInfo.getId());
        updateUserLogin.setLastLoginIp(IpUtils.getIpAddr());
        updateUserLogin.setLastLoginTime(new Date());
        remoteUserInfoService.updateUserLogin(updateUserLogin,SecurityConstants.INNER);

        return loginUser;
    }
}
